package org.study.id.leaf.core.segment.model;

import lombok.Getter;
import lombok.Setter;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.*;

/**
 * 双buffer
 */
public class SegmentBuffer {
    @Setter
    @Getter
    private String key;
    /**
     * 双buffer
     */
    @Getter
    private Segment[] segments;
    /**
     * 当前的使用的segment的index
     */
    @Getter
    private volatile int currentPos;
    /**
     * 下一个segment是否处于可切换状态
     */
    @Setter
    @Getter
    private volatile boolean nextReady;
    /**
     * 是否初始化完成
     */
    @Setter
    @Getter
    private volatile boolean initOk;
    /**
     * 线程是否在运行中
     */
    @Getter
    private final AtomicBoolean threadRunning;
    private final ReadWriteLock lock;
    @Setter
    @Getter
    private volatile int step;
    @Setter
    @Getter
    private volatile int minStep;
    @Setter
    @Getter
    private volatile long updateTimestamp;

    public SegmentBuffer() {
        segments = new Segment[]{new Segment(this), new Segment(this)};
        currentPos = 0;
        nextReady = false;
        initOk = false;
        threadRunning = new AtomicBoolean(false);
        lock = new ReentrantReadWriteLock();
    }

    public Segment getCurrent() {
        return segments[currentPos];
    }

    public int nextPos() {
        return (currentPos + 1) % 2;
    }

    public void switchPos() {
        currentPos = nextPos();
    }


    public Lock rLock() {
        return lock.readLock();
    }

    public Lock wLock() {
        return lock.writeLock();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("SegmentBuffer {");
        sb.append("key='").append(key).append('\'')
                .append(", segments=").append(Arrays.toString(segments))
                .append(", currentPos=").append(currentPos)
                .append(", nextReady=").append(nextReady)
                .append(", initOk=").append(initOk)
                .append(", threadRunning=").append(threadRunning)
                .append(", step=").append(step)
                .append(", minStep=").append(minStep)
                .append(", updateTimestamp=").append(updateTimestamp)
                .append('}');
        return sb.toString();
    }
}
